import os
from pathlib import Path
import io
import win32com.client
import fitz
from docx import Document
from docx.shared import Inches
from PIL import Image
import pandas as pd
from pptx import Presentation
from .utils import Logger

logger = Logger()

class ConversionError(Exception):
    pass

class DocumentConverter:
    SUPPORTED_CONVERSIONS = {
        ('.pdf', '.docx'): 'pdf_to_docx',
        ('.docx', '.pdf'): 'docx_to_pdf',
        ('.xlsx', '.pdf'): 'excel_to_pdf',
        ('.pptx', '.pdf'): 'ppt_to_pdf',
        ('.pdf', '.xlsx'): 'pdf_to_excel',
        ('.pdf', '.pptx'): 'pdf_to_ppt',
        ('.docx', '.xlsx'): 'word_to_excel',
        ('.docx', '.pptx'): 'word_to_ppt',
        ('.xlsx', '.docx'): 'excel_to_word',
        ('.xlsx', '.pptx'): 'excel_to_ppt',
        ('.pptx', '.docx'): 'ppt_to_word',
        ('.pptx', '.xlsx'): 'ppt_to_excel',
    }
    
    def __init__(self):
        self.current_progress = 0
        self.progress_callback = None
        
    def set_progress_callback(self, callback):
        self.progress_callback = callback
        
    def update_progress(self, value, message=""):
        self.current_progress = value
        if self.progress_callback:
            self.progress_callback(value, message)
        
    def pdf_to_docx(self, input_file: str, output_file: str) -> bool:
        try:
            doc = Document()
            pdf_document = fitz.open(input_file)
            total_pages = len(pdf_document)
            
            logger.info(f"开始转换PDF文件，共 {total_pages} 页")
            self.update_progress(0, f"开始转换PDF文件，共 {total_pages} 页")
            
            for page_num in range(total_pages):
                progress = int((page_num + 1) * 100 / total_pages)
                self.update_progress(progress, f"正在处理第 {page_num + 1} 页，共 {total_pages} 页")
                
                page = pdf_document[page_num]
                
                if page_num > 0:
                    doc.add_page_break()
                
                # 提取文本
                blocks = page.get_text("blocks")
                blocks.sort(key=lambda b: (b[1], b[0]))
                
                for block in blocks:
                    text = block[4].strip()
                    if not text:
                        continue
                    doc.add_paragraph(text)
                
                # 提取图片
                for img in page.get_images():
                    try:
                        xref = img[0]
                        base_image = pdf_document.extract_image(xref)
                        image_bytes = base_image["image"]
                        image = Image.open(io.BytesIO(image_bytes))
                        temp_img_path = f"temp_img_{page_num}_{xref}.png"
                        image.save(temp_img_path)
                        doc.add_picture(temp_img_path, width=Inches(6.0))
                        os.remove(temp_img_path)
                    except Exception as e:
                        logger.warning(f"处理图片时出错: {str(e)}")
            
            self.update_progress(100, "正在保存文件...")
            doc.save(output_file)
            pdf_document.close()
            return True
            
        except Exception as e:
            logger.error(f"PDF转Word失败: {str(e)}")
            raise ConversionError(f"PDF转Word失败: {str(e)}")

    def docx_to_pdf(self, input_file: str, output_file: str) -> bool:
        try:
            self.update_progress(0, "正在启动 Word 应用...")
            word = win32com.client.Dispatch("Word.Application")
            
            self.update_progress(25, "正在打开文档...")
            doc = word.Documents.Open(input_file)
            
            self.update_progress(50, "正在转换为PDF...")
            doc.SaveAs(output_file, FileFormat=17)
            
            self.update_progress(75, "正在关闭文档...")
            doc.Close()
            
            self.update_progress(90, "正在关闭 Word 应用...")
            word.Quit()
            
            self.update_progress(100, "转换完成")
            return True
        except Exception as e:
            logger.error(f"Word转PDF失败: {str(e)}")
            raise ConversionError(f"Word转PDF失败: {str(e)}")

    def excel_to_pdf(self, input_file: str, output_file: str) -> bool:
        try:
            self.update_progress(0, "正在启动 Excel 应用...")
            excel = win32com.client.Dispatch("Excel.Application")
            
            self.update_progress(25, "正在打开工作簿...")
            wb = excel.Workbooks.Open(input_file)
            
            self.update_progress(50, "正在转换为PDF...")
            wb.ExportAsFixedFormat(0, output_file)
            
            self.update_progress(75, "正在关闭工作簿...")
            wb.Close()
            
            self.update_progress(90, "正在关闭 Excel 应用...")
            excel.Quit()
            
            self.update_progress(100, "转换完成")
            return True
        except Exception as e:
            logger.error(f"Excel转PDF失败: {str(e)}")
            raise ConversionError(f"Excel转PDF失败: {str(e)}")

    # ... 其他转换方法类似 ...

    @staticmethod
    def get_output_path(input_file: str, target_format: str) -> str:
        input_path = Path(input_file)
        return str(input_path.parent / f"{input_path.stem}.{target_format.lower()}")
    
    @staticmethod
    def validate_input_file(file_path: str) -> None:
        if not os.path.exists(file_path):
            raise FileNotFoundError(f"找不到文件: {file_path}")
        if not os.path.isfile(file_path):
            raise ValueError(f"不是有效的文件: {file_path}")
    
    def convert(self, input_file: str, target_format: str) -> bool:
        try:
            logger.info(f"开始转换文件: {input_file} -> {target_format}")
            self.validate_input_file(input_file)
            
            input_ext = os.path.splitext(input_file)[1].lower()
            target_ext = f".{target_format.lower()}"
            
            conversion_key = (input_ext, target_ext)
            if conversion_key not in self.SUPPORTED_CONVERSIONS:
                error_msg = f"不支持从 {input_ext} 转换到 {target_ext}"
                logger.error(error_msg)
                raise ConversionError(error_msg)
            
            output_file = self.get_output_path(input_file, target_format)
            conversion_method = getattr(self, self.SUPPORTED_CONVERSIONS[conversion_key])
            
            success = conversion_method(input_file, output_file)
            if success:
                logger.info(f"文件转换成功: {output_file}")
            return success
            
        except Exception as e:
            logger.error(f"转换失败: {str(e)}")
            raise ConversionError(str(e)) 